﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace AutoTLBB.Utilites {
    public class Game : IDisposable {
        #region Properties
        public string CharName { get; private set; }
        public string CharId { get; private set; }
        public IntPtr WindowHandle { get; private set; }
        public int ProcessId { get; private set; }
        public int Blood { get; set; }
        public int MaxBlood { get; set; }
        public int Mana { get; set; }
        public int MaxMana { get; set; }
        public int PetNo { get; set; }
        public int PetBlood { get; set; }
        public bool IsHideGame { get; set; }
        public float LocationX { get; set; }
        public float LocationY { get; set; }
        public SkillDefine BasicSkill { get; set; }
        public UserKey Target { get; set; }
        private ProcessMemoryReader m_reader;
        #endregion Properties
        #region Methods
        public void Run() {

        }
        private void Init() {
            CharName = GetCharName();
            CharId = GetCharId();
            Refresh();
        }
        private void Refresh() {
            RefreshBlood();
            RefreshMaxBlood();
            RefreshMana();
            RefreshMaxMana();
            RefreshLocation();
            
        }
        public void RefreshLocation() {
            LocationX = GetLocationX();
            LocationY = GetLocationY();
        }
        public Game(int processId) {
            ProcessId = processId;
            m_reader = new ProcessMemoryReader(processId);
            Init();
        }
        /// <summary>
        /// Gets the character blood.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        private void RefreshBlood() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, 0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset2), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset3), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_hp_nv_current);
            Blood = BitConverter.ToInt32(buffer, 0);
        }
        /// <summary>
        /// Gets the max character blood.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        private void RefreshMaxBlood() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, 0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset2), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset3), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_hp_nv_max);
            m_reader.CloseHandle();
            MaxBlood= BitConverter.ToInt32(buffer, 0);
        }
        /// <summary>
        /// Gets the ID.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        private string GetCharId() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_id;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_id0), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_id1);
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            m_reader.CloseHandle();

            return BitConverter.ToInt32(buffer, 0).ToString("X").ToString();
        }
        /// <summary>
        /// Gets the location X.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        private float GetLocationX() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_x;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_x0), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_x1);
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            m_reader.CloseHandle();
            return BitConverter.ToSingle(buffer, 0);
        }
        /// <summary>
        /// Gets the location Y.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        private float GetLocationY() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_y;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_y0), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_y1);
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            m_reader.CloseHandle();
            return BitConverter.ToSingle(buffer, 0);
        }
        /// <summary>
        /// Gets the character mana.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        private void RefreshMana() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset2), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset3), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_mana_nv_current);
            m_reader.CloseHandle();
            Mana= BitConverter.ToInt32(buffer, 0);

        }
        /// <summary>
        /// Gets the max character mana.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        private void RefreshMaxMana() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset2), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset3), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_mana_nv_max);
            m_reader.CloseHandle();
            MaxMana = BitConverter.ToInt32(buffer, 0);
        }
        /// <summary>
        /// Gets the name of the character.
        /// </summary>
        /// <param name="processId">The process id.</param>
        /// <returns></returns>
        private string GetCharName() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, 0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset2), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset3), 0);
            byte[] bytes = m_reader.ReadOffset(dwAddress, Variable.offset_name_nv);
            m_reader.CloseHandle();
            string str = new UTF7Encoding().GetString(bytes);
            if (BitConverter.ToInt32(bytes, 0) == 0) {
                str = "Chưa đăng nhập";
            }
            return str;
        }
        /// <summary>
        /// Gets the run.
        /// </summary>
        /// <param name="processId">The process id.</param>
        /// <returns></returns>
        public int GetRun() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_run;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_run0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_run1), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_run2);
            m_reader.CloseHandle();
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            return BitConverter.ToInt32(buffer, 0);

        }
        /// <summary>
        /// Gets the boss blood.
        /// </summary>
        /// <param name="processId">The process id.</param>
        /// <returns></returns>
        public int GetBossBlood() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.bass_address_boss;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss2), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss3), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss4), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss5), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss6), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss7), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss8), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_boss9), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_boss10);
            m_reader.CloseHandle();
            return BitConverter.ToInt32(buffer, 0);

        }
        /// <summary>
        /// Gets the monster blood.
        /// </summary>
        /// <param name="processId">The process id.</param>
        /// <returns></returns>
        public int GetMonsterBlood() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.bass_address_monster;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster2), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster3), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster4), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster5), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster6), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster7), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster8), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_monster9), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_monster10);
            m_reader.CloseHandle();
            return BitConverter.ToInt32(buffer, 0);

        }
        /// <summary>
        /// Gets the pet blood.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public int GetPetBlood() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_pet_hp_current;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_pet0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_pet1), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_pet2 + ((uint)(NumberPet() * Variable.offset_pet_chenhlech)));
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            m_reader.CloseHandle();
            return BitConverter.ToInt32(buffer, 0);


        }
        /// <summary>
        /// Gets the max pet blood.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public int GetMaxPetBlood() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_pet_hp_current;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_pet0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_pet1), 0);
            byte[] maxHp = m_reader.ReadOffset(dwAddress, Variable.base_address_pet_hp_max + ((uint)(NumberPet() * Variable.offset_pet_chenhlech)));
            m_reader.CloseHandle();
            return BitConverter.ToInt32(maxHp, 0);
        }
        /// <summary>
        /// Numbers the pet.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public int NumberPet() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_number_pet;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_number_pet0), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_number_pet1);
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            m_reader.CloseHandle();
            return BitConverter.ToInt32(buffer, 0);


        }
        /// <summary>
        /// Gets the id character.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        private int GetIdCharacter() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, 0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset2), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset3), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_name_nv);
            m_reader.CloseHandle();
            return BitConverter.ToInt32(buffer, 0);

        }
        /// <summary>
        /// Determines whether the specified id is auto.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public int HasAutoQuestion() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_auto;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_auto0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_auto1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_auto2), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_auto3);
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            m_reader.CloseHandle();
            return BitConverter.ToInt32(buffer, 0);
        }
        /// <summary>
        /// Determines whether the specified id is hit.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public int IsHit() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_nhanvat_hit0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_nhanvat_hit1), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_nhanvat_hit2);
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            m_reader.CloseHandle();
            return BitConverter.ToInt32(buffer, 0);

        }
        /// <summary>
        /// Determines whether the specified id is target.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public int IsTarget() {
            m_reader.OpenProcess();
            uint dwAddress = Variable.base_address_target;
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_target0), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_target1), 0);
            dwAddress = BitConverter.ToUInt32(m_reader.ReadOffset(dwAddress, Variable.offset_target2), 0);
            byte[] buffer = m_reader.ReadOffset(dwAddress, Variable.offset_target3);
            dwAddress = BitConverter.ToUInt32(buffer, 0);
            m_reader.CloseHandle();
            return BitConverter.ToInt32(buffer, 0);


        }
        
        /// <summary>
        /// Presses the key.
        /// </summary>
        /// <param name="handle">The handle.</param>
        /// <param name="key">The key.</param>
        public void PressKey(IntPtr handle, UserKey key) {
            ReadMemory.SendMessage(handle, ReadMemory.WM_KEYDOWN, ConVertKey(key.ToString()), 0);
            Thread.Sleep(TimeSpan.FromSeconds(0.1));
            ReadMemory.SendMessage(handle, ReadMemory.WM_KEYUP, ConVertKey(key.ToString()), 0);
        }
        /// <summary>
        /// Cons the vert key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        private int ConVertKey(string key) {
            switch (key) {
                case "F1":
                    return 0x70;

                case "F2":
                    return 0x71;

                case "F3":
                    return 0x72;

                case "F4":
                    return 0x73;

                case "F5":
                    return 0x74;

                case "F6":
                    return 0x75;

                case "F7":
                    return 0x76;

                case "F8":
                    return 0x77;

                case "F9":
                    return 120;

                case "F10":
                    return 0x79;

                case "F11":
                    return 0x7a;

                case "F12":
                    return 0x7b;

                case "Insert":
                    return 0x2d;

                case "Delete":
                    return 0x2e;

                case "Home":
                    return 0x24;

                case "End":
                    return 0x23;

                case "PageUp":
                    return 0x21;

                case "PageDown":
                    return 0x22;

                case "0":
                    return 0x30;

                case "1":
                    return 0x31;

                case "2":
                    return 50;

                case "3":
                    return 0x33;

                case "4":
                    return 0x34;

                case "5":
                    return 0x35;

                case "6":
                    return 0x36;

                case "7":
                    return 0x37;

                case "8":
                    return 0x38;

                case "9":
                    return 0x39;
            }
            return 0;
        }
        /// <summary>
        /// Turns the off game.
        /// </summary>
        /// <param name="id">The id.</param>
        public  void TurnOffGame() {
            this.m_reader.Dispose();
            Process.GetProcessById(ProcessId).Kill() ;
        }
        /// <summary>
        /// Shows the game.
        /// </summary>
        /// <param name="window">The window.</param>
        /// <param name="hidden">if set to <c>true</c> [hidden].</param>
        public void ShowGame(IntPtr window, bool hidden) {
            ReadMemory.ShowWindow(window, hidden ? 0 : 9);
        }
        /// <summary>
        /// Radiuses the model.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        public double RadiusModel(CharacterModel model) {
            
            int num = Math.Abs((int)(model.LocationX - Convert.ToInt32(GetLocationX())));
            int num2 = Math.Abs((int)(model.LocationY - Convert.ToInt32(GetLocationY())));
            return Math.Sqrt((double)((num * num) + (num2 * num2)));
        }
        #endregion Methods
        #region Static Methods
        /// <summary>
        /// Stops the simple sound.
        /// </summary>
        public static void StopSimpleSound() {
            try {
                ReadMemory.mciSendString("stop YinYangMedia", null, 0, IntPtr.Zero);
                ReadMemory.mciSendString("close YinYangMedia", null, 0, IntPtr.Zero);
            } catch {
                try {
                    ReadMemory.mciSendString("close YinYangMedia", null, 0, IntPtr.Zero);
                } catch {
                }
            }
        }
        /// <summary>
        /// Plays the simple sound.
        /// </summary>
        /// <param name="pathSound">The path sound.</param>
        public static void PlaySimpleSound(string pathSound) {
            ReadMemory.mciSendString("open \"" + pathSound + "\" type mpegvideo alias YinYangMedia", null, 0, IntPtr.Zero);
            ReadMemory.mciSendString("play YinYangMedia", null, 0, IntPtr.Zero);
        }
        #endregion Static Methods
        #region IDisposable Members

        public void Dispose() {
            m_reader.Dispose();
        }

        #endregion
    }
}
